#ifndef _MY_UTIL_
#define _MY_UTIL_
#include<iostream>
#include<fstream>
#include<string>
#include<vector>
#include<sys/stat.h>
#include"bundle.h"
#include<experimental/filesystem>
#include<jsoncpp/json/json.h>
namespace cloud{
    namespace fs = std::experimental::filesystem;
    class FileUtil{//文件实用类工具设计
        private:
            std::string _filename;
        public:
            FileUtil(const std::string & filename):_filename(filename){}//构造函数
            int64_t FileSize(){
                    struct stat st;//获取文件信息接口
                    if(stat(_filename.c_str() , &st)< 0){
                        return -1;
                        std::cout<< "Get file_size failed\n";
                        return -1;
                    }
                    return st.st_size;//返回文件大小
                
            }//获取文件大小
            time_t LastTime(){
                    struct stat st;//获取文件信息接口
                    if(stat(_filename.c_str() , &st)< 0){
                        return -1;
                        std::cout<< "Get file_size failed\n";
                        return -1;
                    }
                    return st.st_mtime;
                
            }//文件最后一次修改时间
            time_t LastATime(){
                    struct stat st;//获取文件信息接口
                    if(stat(_filename.c_str() , &st)< 0){
                        return -1;
                        std::cout<< "Get file_size failed\n";
                        return -1;
                    }
                    return st.st_atime;
                
            }//文件最后一次访问时间
            std::string FileName(){
                // ./abc/test.tst
                size_t pos = _filename.find_last_of("/");//找到路径的最后一个斜杠
                if(pos == std::string::npos){//本身就是文件名
                    return _filename;
                }
                return _filename.substr(pos+1);
            }//文件名称获取
            bool GetPosLen(std:: string *body , size_t pos ,size_t len){//获取指定长度的数据
                std::ifstream ifs;
                ifs.open(_filename , std::ios::binary);//二进制打开文件
                if(ifs.is_open() == false){
                    std::cout<< "open file failed\n";
                    return false ;
                }
                size_t fsize = this->FileSize();//获取当前文件大小
                if(pos + len > fsize){//超出文件大小 
                    std::cout<<" get file len is erron\n";
                    return false;
                }

                ifs.seekg(pos , std::ios::beg);
                body->resize(len);
                ifs.read(&(*body)[0] , len);//读取文件 
                if(ifs.good() == false){
                    std::cout<<"get file content failed\n";
                    ifs.close();
                    return false;
                }
                ifs.close();
                return true;
            }
            bool GetContent(std:: string *body){//获取文件全部内容
                size_t fsize = this->FileSize();//获取当前文件大小
                return GetPosLen(body , 0 ,fsize);
            }
            bool SetContent(const std::string &body){//写入文件数据
                std::ofstream ofs;
                ofs.open(_filename , std::ios::binary);
                if(ofs.is_open() == false){
                    std::cout<<"write open failed.\n";
                    return false;
                }
                ofs.write(&body[0] , body.size());//写入数据
                if(ofs.good() == false){
                    std::cout<<"write file content failed!\n";
                    ofs.close();
                    return false;
                }
                ofs.close();
                return true;
            }

            bool Compress(const std::string &packname){//压缩功能
                //1.读取源文件数据
                std::string body;
                if(this->GetContent(&body) == false){
                    std::cout<< "compress get file content failen!\n";
                    return false;
                }
                //2.对文件进行压缩
                std::string packed = bundle::pack(bundle::LZIP, body);
                //将压缩的数据存入数据包文件
                FileUtil fu(packname);
                if(fu.SetContent(packed) == false){
                    std::cout<<" compress write packed failed!\n";
                    return false;
                }
                return true;
            }
            bool uncompress(const std::string &filenmae){
                //1.将当前压缩包数据读取
                std::string body;
                if(this->GetContent(&body) == false){
                    std::cout<<"uncompress write packed data failed!\n";
                    return false;
                }
                //将压缩数据解压缩
                std::string unpacked = bundle::unpack(body);
                //将解压缩数据写入到新文件
                FileUtil fu(filenmae);
                if(fu.SetContent(unpacked) == false){
                     std::cout<<" uncompress write packed failed!\n";
                    return false;
                }
                return true;
            }
            
            bool Exists(){//判断文件是否存在
                return fs::exists(_filename);
            }
            bool CreateDirectory(){//创建目录
                if(this->Exists()) return true;
                return fs::create_directories(_filename);
            }
            bool ScanDirectory(std::vector<std::string> * arry){//列出这个目录下的文件
                for(auto & p: fs::directory_iterator(_filename)){
                    if(fs::is_directory(p) == true){//如果是目录
                        continue;
                    }
                    //relative_path 带有路劲的文件名
                    arry->push_back(fs::path(p).relative_path().string());
                }
                return true;
            }
    };

    class JsonUtil{
        public:
            //序列化函数
            static bool Serialize( Json::Value &root , std::string * str){
                //创建一个StreamWriterBuilder实例
                Json::StreamWriterBuilder swb ;

                std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());

                std::stringstream ss;
                //开始序列化,json序列化的字符串保存在ss中
                sw->write(root , &ss);
                *str = ss.str();
            }
            static bool UnSerialize(const std::string &str , Json::Value * root){
                //反序列化过程
                Json::CharReaderBuilder cwb;

                std::unique_ptr<Json::CharReader> cw(cwb.newCharReader());

                std::string err;

                bool ret = cw->parse(str.c_str() ,str.c_str() + str.size() , root , &err);
                if(ret == false){
                    std::cout<<"parse error"<<err<<std::endl;
                }
                return true;
            }
    };


}
#endif